/*
 * Copyright (C) 2014 Realtek Semiconductor Corp.
 * All Rights Reserved.
 *
 * This program is the proprietary software of Realtek Semiconductor
 * Corporation and/or its licensors, and only be used, duplicated,
 * modified or distributed under the authorized license from Realtek.
 *
 * ANY USE OF THE SOFTWARE OTHER THAN AS AUTHORIZED UNDER
 * THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
 *
 */


#include "app_basic.h"

MIB_TABLE_INFO_T gMibOmciTableInfo;
MIB_ATTR_INFO_T  gMibOmciAttrInfo[MIB_TABLE_OMCI_ATTR_NUM];
MIB_TABLE_OMCI_T gMibOmciDefRow;
MIB_TABLE_OPER_T gMibOmciOper;


extern omci_mulget_info_ts gOmciMulGetData[OMCI_MSG_BASELINE_PRI_NUM];
extern int MIB_TABLE_TOTAL_NUMBER;



static GOS_ERROR_CODE omci_mib_omci_oper_reset(UINT32 args_num, ...)
{
    MIB_TABLE_OMCI_T mibOmci;
    MIB_TABLE_INDEX tableIndex;
    omci_meType_tbl_entry_t *pEntry,*pTmpEntry;
    UINT32  meType, meClassId;
    UINT16  i, isBiggest=0;

    OMCI_LOG(OMCI_LOG_LEVEL_INFO, "Resetting MIB: OMCI ME");

    MIB_Default(MIB_TABLE_OMCI_INDEX, &mibOmci, sizeof(MIB_TABLE_OMCI_T));

    mibOmci.EntityId = 0;
    mibOmci.MeTypeTbl_size = 0;

    /*Set Me Type table*/
    for(i = 0, tableIndex = MIB_TABLE_FIRST_INDEX; i < MIB_TABLE_TOTAL_NUMBER;
        i++, tableIndex = MIB_TABLE_NEXT_INDEX(tableIndex))
    {
        meType = MIB_GetTableStdType(tableIndex);
        if (meType & OMCI_ME_TYPE_PRIVATE)
        {
            continue;
        }
        mibOmci.MeTypeTbl_size ++;
        meClassId = MIB_GetTableClassId(tableIndex);

        pEntry = (omci_meType_tbl_entry_t*)malloc(sizeof(omci_meType_tbl_entry_t));
        if(!pEntry)
        {
            OMCI_LOG(OMCI_LOG_LEVEL_ERR,"Malloc omci_meType_tbl Entry Fail");
            return GOS_FAIL;
        }
        pEntry->tableEntry.meTypeTbl = meClassId;

        /*Insert by class id order*/
        LIST_FOREACH(pTmpEntry, &mibOmci.meType_head, entries)
        {
            if(pTmpEntry->tableEntry.meTypeTbl >= meClassId)
            {
                break;
            }
            if(NULL == LIST_NEXT(pTmpEntry, entries))
            {
                isBiggest = 1;
                break;
            }
        }
        if(isBiggest)
        {
            LIST_INSERT_AFTER(pTmpEntry, pEntry, entries);
            isBiggest = 0;
        }
        else if(pTmpEntry)
        {
            LIST_INSERT_BEFORE(pTmpEntry, pEntry, entries);
        } else {
            LIST_INSERT_HEAD(&mibOmci.meType_head, pEntry, entries);
        }

    }

    GOS_ASSERT(GOS_OK == MIB_Set(MIB_TABLE_OMCI_INDEX, &mibOmci, sizeof(MIB_TABLE_OMCI_T)));

    return GOS_OK;
}



GOS_ERROR_CODE OmciDumpMib(void *pData, MIB_TABLE_INFO_T *pTblInfo)
{
	MIB_TABLE_OMCI_T *pOmci = (MIB_TABLE_OMCI_T*)pData;
	omci_meType_tbl_entry_t *pEntry;
	UINT32 i = 0;
	CHAR tmpBuf[100];

	OMCI_PRINT("EntityId: 0x%02x", pOmci->EntityId);

	OMCI_PRINT("MsgTypeTbl: ");
	LIST_FOREACH(pEntry,&pOmci->meType_head, entries)
	{
		sprintf(tmpBuf+(i*7), "%05d, ", pEntry->tableEntry.meTypeTbl);

		if( 9 == i )
		{
			OMCI_PRINT("%s", tmpBuf);
			i = 0;
		} else {
			i++;
		}

	}
	if( 9 != i )
	{
		OMCI_PRINT("%s", tmpBuf);
	}

	OMCI_PRINT("%d\n", pOmci->MeTypeTbl_size);
	OMCI_PRINT("MsgTypeTbl: 0x%02x", pOmci->MsgTypeTbl[0]);

	return GOS_OK;
}

GOS_ERROR_CODE OmciDrvCfg(void* pOldRow, void* pNewRow, MIB_OPERA_TYPE operationType, MIB_ATTRS_SET attrSet, UINT32 pri)
{
    MIB_TABLE_OMCI_T *pOmci;

    OMCI_LOG(OMCI_LOG_LEVEL_DBG, "Start %s...", __FUNCTION__);

    pOmci = (MIB_TABLE_OMCI_T*)pNewRow;

    switch (operationType){
        case MIB_ADD:
            OMCI_LOG(OMCI_LOG_LEVEL_DBG,"Omci --> ADD");
            break;
        case MIB_GET:
        {
            MIB_ATTR_INDEX	attrIndex;
            UINT8 *ptr = NULL;
            omci_meType_tbl_entry_t *pEntry;
            UINT16 classId;
            UINT32 attrSize;
            
            
            OMCI_LOG(OMCI_LOG_LEVEL_DBG,"Omci --> GET");

            attrIndex = MIB_TABLE_OMCI_METYPETBL_INDEX;
            if (MIB_IsInAttrSet(&attrSet, attrIndex))
            {
                OMCI_PRINT("OMCI Get ME Table");

                attrSize = MIB_TABLE_METYPETBL_LEN * (pOmci->MeTypeTbl_size);
 
                ptr  = gOmciMulGetData[pri].attribute[attrIndex].pAttrValue; 
                if(ptr && attrSize != gOmciMulGetData[pri].attribute[attrIndex].attrSize) /*attrSize change , first free old buffer */
                {
                    OMCI_PRINT("%s() %d ptr=0x%p, size= %u", __FUNCTION__, __LINE__, ptr, gOmciMulGetData[pri].attribute[attrIndex].attrSize);
                    gOmciMulGetData[pri].attribute[attrIndex].pAttrValue = NULL;
                    free(ptr);
                    ptr = NULL;
                }
                
                if(NULL == ptr && attrSize>0) /*Allocate new buffer */
                {
                    gOmciMulGetData[pri].attribute[attrIndex].pAttrValue = (UINT8 *)malloc(attrSize);
                    ptr  = gOmciMulGetData[pri].attribute[attrIndex].pAttrValue; 
                    OMCI_PRINT("%s() %d ptr=0x%p, size= %u", __FUNCTION__, __LINE__, ptr, gOmciMulGetData[pri].attribute[attrIndex].attrSize);   
                }

                gOmciMulGetData[pri].attribute[attrIndex].attrSize = attrSize;
                gOmciMulGetData[pri].attribute[attrIndex].attrIndex = attrIndex;
                gOmciMulGetData[pri].attribute[attrIndex].doneSeqNum = 0;
                gOmciMulGetData[pri].attribute[attrIndex].maxSeqNum =
                (gOmciMulGetData[pri].attribute[attrIndex].attrSize + OMCI_MSG_BASELINE_GET_NEXT_RSP_LIMIT - 1) / OMCI_MSG_BASELINE_GET_NEXT_RSP_LIMIT;

                if(ptr)
                {                                      
                    LIST_FOREACH(pEntry, &pOmci->meType_head, entries)
                    {
                        classId = GOS_Htons(pEntry->tableEntry.meTypeTbl);
                        memcpy(ptr, &classId, MIB_TABLE_METYPETBL_LEN);
                        ptr += MIB_TABLE_METYPETBL_LEN;
                    }

                }

            }
            break;
        }
    case MIB_DEL:
    	OMCI_LOG(OMCI_LOG_LEVEL_DBG,"Omci --> DEL");
    	break;
    default:
    	return GOS_FAIL;
    	break;
    }

    OMCI_PRINT("OMCI END");
    return GOS_OK;
}
GOS_ERROR_CODE mibTable_init(MIB_TABLE_INDEX tableId)
{
    UINT8 proprietary_mib_cb_bitmask = 0;
    UINT8 isIgnore = 0;
    if(GOS_OK == omci_ignore_mib_table_check(OMCI_ME_CLASS_OMCI, OMCI_ME_CLASS_SUB_DEFAULT, &isIgnore))
    {
        if(isIgnore)
        {
	        OMCI_PRINT("Ignore classId:%d", OMCI_ME_CLASS_OMCI);
            return GOS_FAIL;
        }

    }

    gMibOmciTableInfo.Name = "Omci";
    gMibOmciTableInfo.ShortName = "OMCI";
    gMibOmciTableInfo.Desc = "OMCI";
    gMibOmciTableInfo.ClassId = (UINT32)(OMCI_ME_CLASS_OMCI);
    gMibOmciTableInfo.InitType = (UINT32)(OMCI_ME_INIT_TYPE_ONU);
    gMibOmciTableInfo.StdType = (UINT32)(OMCI_ME_TYPE_STANDARD | OMCI_ME_TYPE_NOT_MIB_UPLOAD);
    gMibOmciTableInfo.ActionType = (UINT32)(OMCI_ME_ACTION_GET | OMCI_ME_ACTION_GET_NEXT);
    gMibOmciTableInfo.pAttributes = &(gMibOmciAttrInfo[0]);

    gMibOmciTableInfo.attrNum = MIB_TABLE_OMCI_ATTR_NUM;
    gMibOmciTableInfo.entrySize = sizeof(MIB_TABLE_OMCI_T);
    gMibOmciTableInfo.pDefaultRow = &gMibOmciDefRow;

    gMibOmciAttrInfo[MIB_TABLE_OMCI_ENTITYID_INDEX - MIB_TABLE_FIRST_INDEX].Name = "EntityId";
    gMibOmciAttrInfo[MIB_TABLE_OMCI_METYPETBL_INDEX - MIB_TABLE_FIRST_INDEX].Name = "MeTypeTbl";
    gMibOmciAttrInfo[MIB_TABLE_OMCI_MSGTYPETBL_INDEX - MIB_TABLE_FIRST_INDEX].Name = "MsgTypeTbl";

    gMibOmciAttrInfo[MIB_TABLE_OMCI_ENTITYID_INDEX - MIB_TABLE_FIRST_INDEX].Desc = "Entity ID";
    gMibOmciAttrInfo[MIB_TABLE_OMCI_METYPETBL_INDEX - MIB_TABLE_FIRST_INDEX].Desc = "ME type table";
    gMibOmciAttrInfo[MIB_TABLE_OMCI_MSGTYPETBL_INDEX - MIB_TABLE_FIRST_INDEX].Desc = "Message type table";

    gMibOmciAttrInfo[MIB_TABLE_OMCI_ENTITYID_INDEX - MIB_TABLE_FIRST_INDEX].DataType = MIB_ATTR_TYPE_UINT16;
    gMibOmciAttrInfo[MIB_TABLE_OMCI_METYPETBL_INDEX - MIB_TABLE_FIRST_INDEX].DataType = MIB_ATTR_TYPE_TABLE;
    gMibOmciAttrInfo[MIB_TABLE_OMCI_MSGTYPETBL_INDEX - MIB_TABLE_FIRST_INDEX].DataType = MIB_ATTR_TYPE_TABLE;

    gMibOmciAttrInfo[MIB_TABLE_OMCI_ENTITYID_INDEX - MIB_TABLE_FIRST_INDEX].Len = 2;
    gMibOmciAttrInfo[MIB_TABLE_OMCI_METYPETBL_INDEX - MIB_TABLE_FIRST_INDEX].Len = 2;
    gMibOmciAttrInfo[MIB_TABLE_OMCI_MSGTYPETBL_INDEX - MIB_TABLE_FIRST_INDEX].Len = 1;

    gMibOmciAttrInfo[MIB_TABLE_OMCI_ENTITYID_INDEX - MIB_TABLE_FIRST_INDEX].IsIndex = TRUE;
    gMibOmciAttrInfo[MIB_TABLE_OMCI_METYPETBL_INDEX - MIB_TABLE_FIRST_INDEX].IsIndex = FALSE;
    gMibOmciAttrInfo[MIB_TABLE_OMCI_MSGTYPETBL_INDEX - MIB_TABLE_FIRST_INDEX].IsIndex = FALSE;

    gMibOmciAttrInfo[MIB_TABLE_OMCI_ENTITYID_INDEX - MIB_TABLE_FIRST_INDEX].MibSave = TRUE;
    gMibOmciAttrInfo[MIB_TABLE_OMCI_METYPETBL_INDEX - MIB_TABLE_FIRST_INDEX].MibSave = TRUE;
    gMibOmciAttrInfo[MIB_TABLE_OMCI_MSGTYPETBL_INDEX - MIB_TABLE_FIRST_INDEX].MibSave = TRUE;

    gMibOmciAttrInfo[MIB_TABLE_OMCI_ENTITYID_INDEX - MIB_TABLE_FIRST_INDEX].OutStyle = MIB_ATTR_OUT_HEX;
    gMibOmciAttrInfo[MIB_TABLE_OMCI_METYPETBL_INDEX - MIB_TABLE_FIRST_INDEX].OutStyle = MIB_ATTR_OUT_HEX;
    gMibOmciAttrInfo[MIB_TABLE_OMCI_MSGTYPETBL_INDEX - MIB_TABLE_FIRST_INDEX].OutStyle = MIB_ATTR_OUT_HEX;

    gMibOmciAttrInfo[MIB_TABLE_OMCI_ENTITYID_INDEX - MIB_TABLE_FIRST_INDEX].OltAcc = OMCI_ME_ATTR_ACCESS_READ;
    gMibOmciAttrInfo[MIB_TABLE_OMCI_METYPETBL_INDEX - MIB_TABLE_FIRST_INDEX].OltAcc = OMCI_ME_ATTR_ACCESS_READ;
    gMibOmciAttrInfo[MIB_TABLE_OMCI_MSGTYPETBL_INDEX - MIB_TABLE_FIRST_INDEX].OltAcc = OMCI_ME_ATTR_ACCESS_READ;

    gMibOmciAttrInfo[MIB_TABLE_OMCI_ENTITYID_INDEX - MIB_TABLE_FIRST_INDEX].AvcFlag = FALSE;
    gMibOmciAttrInfo[MIB_TABLE_OMCI_METYPETBL_INDEX - MIB_TABLE_FIRST_INDEX].AvcFlag = FALSE;
    gMibOmciAttrInfo[MIB_TABLE_OMCI_MSGTYPETBL_INDEX - MIB_TABLE_FIRST_INDEX].AvcFlag = FALSE;

    gMibOmciAttrInfo[MIB_TABLE_OMCI_ENTITYID_INDEX - MIB_TABLE_FIRST_INDEX].OptionType = OMCI_ME_ATTR_TYPE_MANDATORY;
    gMibOmciAttrInfo[MIB_TABLE_OMCI_METYPETBL_INDEX - MIB_TABLE_FIRST_INDEX].OptionType = OMCI_ME_ATTR_TYPE_MANDATORY;
    gMibOmciAttrInfo[MIB_TABLE_OMCI_MSGTYPETBL_INDEX - MIB_TABLE_FIRST_INDEX].OptionType = OMCI_ME_ATTR_TYPE_MANDATORY;

    gMibOmciDefRow.EntityId = 0;
    memset(&gMibOmciDefRow.MeTypeTbl,0x0, MIB_TABLE_METYPETBL_LEN);
    memset(&gMibOmciDefRow.MsgTypeTbl,0x0, MIB_TABLE_MSGTYPETBL_LEN);
	LIST_INIT(&gMibOmciDefRow.meType_head);
	LIST_INIT(&gMibOmciDefRow.msgType_head);

    memset(&gMibOmciOper, 0x0, sizeof(MIB_TABLE_OPER_T));
    gMibOmciOper.meOperDrvCfg = OmciDrvCfg;
    gMibOmciOper.meOperConnCheck = NULL;
    gMibOmciOper.meOperDump = OmciDumpMib;
    gMibOmciOper.meOperConnCfg = NULL;
    gMibOmciOper.meOperAvlTreeAdd = NULL;
    gMibOmciOper.meOperAlarmHandler = NULL;
    gMibOmciOper.meOperTestHandler = NULL;
    gMibOmciOper.meOperCb[PROPRIETARY_MIB_CB_RESET] = omci_mib_omci_oper_reset;

    MIB_TABLE_OMCI_INDEX = tableId;
    MIB_InfoRegister(tableId, &gMibOmciTableInfo, &gMibOmciOper);
    MIB_RegisterCallback(tableId, NULL, NULL);


    proprietary_mib_cb_bitmask = (1 << PROPRIETARY_MIB_CB_RESET);
    MIB_Proprietary_Reg(tableId, proprietary_mib_cb_bitmask);


    return GOS_OK;
}

